﻿// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
//
// MainPage.xaml.h
// Declaration of the MainPage class
//

#pragma once

#include "BasicTimer.h"
#include "MainPage.g.h"
#include "Common\NavigationHelper.h"
#include "DataModel\ForecastManager.h"
#include "ILocationService.h"
#include "LiveTileScheduler.h"
#include "Pin.h"

namespace Weathr
{
    [Windows::UI::Xaml::Data::Bindable]
    [Windows::Foundation::Metadata::WebHostHidden]
    public ref class MainPage sealed
    {
    public:
        MainPage();
        property Windows::Foundation::Collections::PropertySet^ DefaultViewModel
        {
            Windows::Foundation::Collections::PropertySet^ get();
        }
        property Common::NavigationHelper^ NavigationHelper
        {
            Common::NavigationHelper^ get();
        }
    protected:
        virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
        virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;

    private:
        // Holds the animations that are assocaited with each location.
        struct ForecastAnimations
        {
            Forecast^ Forecast;
            Windows::UI::Xaml::Media::Animation::Storyboard^ PopupAnimation;
            Windows::UI::Xaml::Media::Animation::Storyboard^ FadeAnimation;
            Windows::UI::Xaml::Media::Animation::Storyboard^ CurrentAnimation;
            Windows::UI::Xaml::Media::Animation::Storyboard^ NeedleAnimation;
        };

        std::shared_ptr<ExceptionPolicy> m_exceptionPolicy;

        // Tracks rendering event registration.
        Windows::Foundation::EventRegistrationToken m_eventToken;

        // Reference to central ForecastManager object.
        ForecastManager^ m_forecastManager;

        // Maps the UID of each Forecast object to its UI animations.
        std::map<uint32_t, ForecastAnimations> m_animationStoryboards;

        //
        // These variables are used for the pinning feature.
        //

        std::shared_ptr<Web::ILocationService> m_locationService;
        Pin^ m_pin;
        bool m_lastPointValid;
        Windows::Foundation::Point m_lastPoint;
        concurrency::call<std::shared_ptr<Web::Location>> m_pinLocationResultBuffer;
        concurrency::call<Web::WebException> m_pinLocationErrorBuffer;

        //
        // These variables are used to update the live tile.
        //

        BasicTimer^ m_tileUpdateTimer;
        LiveTileScheduler m_liveTileScheduler;
        bool m_updatingLiveTile;
        bool m_updatingSecondaryTile;

        // These queue animations that weren't yet created for later playback.
        std::vector<Forecast^> m_queuedPopupAnimations;
        std::vector<Forecast^> m_queuedFadeAnimations;

        property Forecast^ ForecastTile
        {
            Forecast^ get() { return dynamic_cast<Forecast^>(DefaultViewModel->Lookup("ForecastTile")); }
            void set(Forecast^ value)
            {
                auto current = dynamic_cast<Forecast^>(DefaultViewModel->Lookup("ForecastTile"));
                if (value != current)
                {
                    DefaultViewModel->Insert("ForecastTile", value);
                }
            }
        }

        void LoadState(Platform::Object^ sender, Common::LoadStateEventArgs^ e);
        void SaveState(Platform::Object^ sender, Common::SaveStateEventArgs^ e);

        static Windows::UI::Xaml::DependencyProperty^ _defaultViewModelProperty;
        static Windows::UI::Xaml::DependencyProperty^ _navigationHelperProperty;

        // Updates the list of registered web services in the view model.
        void OnWebServiceRegistered(Platform::String^ serviceName);

        // Retrieves the user's current location.
        concurrency::task<std::shared_ptr<Web::Location>> GetCurrentLocationAsync();

        // Displays the popup animation associated with the given Forecast.
        void ShowPopupAnimation(Forecast^ forecast);
        // Displays the fade animation associated with the given Forecast.
        void ShowFadeAnimation(Forecast^ forecast);
        // Displays the popup animation if the fade animation is current, and vice-versa.
        void ToggleAnimation(Forecast^ forecast);
        // Animates the compass needle associated with the given Forecast.
        void ShowNeedleAnimation(Forecast^ forecast);

        // Updates the live tile.
        concurrency::task<void> UpdateLiveTileAsync();
        // Updates the secondary tile.
        concurrency::task<void> UpdateSecondaryTileAsync(Forecast^ forecast);

        // Updates pin UI.
        void ProcessPinLocation(std::shared_ptr<Web::Location> location);
        // Processes pin locator errors.
        void ProcessPinError(Web::WebException error);
        // Closes pin mode.
        void CancelPin();

        // Called when the weather data changes.
        void OnWeatherDataChanged(Weathr::Forecast ^forecast);
        // Called when the pointer is pressed.
        void OnPointerPressed(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args);
        // Called when the pointer is moved.
        void OnPointerMoved(Windows::UI::Core::CoreWindow^, Windows::UI::Core::PointerEventArgs^ e);
        // Called when the pointer is released.
        void OnPointerReleased(Windows::UI::Core::CoreWindow^ window, Windows::UI::Core::PointerEventArgs^ e);
        // Called when the pin control's size changes.
        void OnPinSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
        // Called when the user chooses the Save command when pin mode is active.
        void SavePinAppBarButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Cancel command when pin mode is active.
        void CancelPinAppBarButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called every time XAML decides to render a frame.
        void OnRendering(Platform::Object^ sender, Platform::Object^ e);
        // Called when the user clicks the 'next' button on the UI to rotate 
        // through locations that are in close proximity with one another.
        void GroupNextButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Pin to Start command.
        void PinToStart_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called whenever the number of items in the Pin to Start popup changes.
        void PinToStartSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
        // Called when the user chooses an item from the Pin to Start popup. 
        void PinToStartItem_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Home command.
        // Takes the user to their home location.
        void Home_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Current command.
        // Takes the user to their current location.
        void Current_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Random command.
        // Takes the user to a random location.
        void Random_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Drop Pin command.
        // Enables pin mode.
        void DropPin_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Change Home command.
        // Brings up a popup that lets the user choose a different home location.
        void ChangeHome_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called whenever the number of items in the Change Home popup changes.
        void ChangeHome_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
        // Called when the user chooses an item from the Change Home popup. 
        void ChangeHomeItem_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user taps a location on the UI.
        void LocationButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the 'WeatherInfo' Canvas element for each location is loaded.
        void WeatherInfo_Loaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses a different date from the top app bar.
        void DateStripGridView_ItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ e);
        // Called when the top app bar is opened.
        void TopAppBar_Opened(Platform::Object^ sender, Platform::Object^ e);
        // Called when the top app bar is closed.
        void TopAppBar_Closed(Platform::Object^ sender, Platform::Object^ e);
        // Called when the user chooses the Manage Locations command.
        void Locations_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        // Called when the user chooses the Refresh command.
        void Refresh_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
    };
}
